﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NextViewer
{
    class Util
    {
        public static double GetDistance(Spot spot, Spot spot2)
        {
            return GetDistance(spot.lat, spot.lon, spot2.lat, spot2.lon);
        }
        public static double GetDistance(double lat1, double lon1,
            double lat2, double lon2)
        {
            int R = 6371;   //R of earth (km)
            double dist;
            double rlat1, rlat2, rlon1, rlon2;

            rlat1 = ToRad(lat1);
            rlat2 = ToRad(lat2);
            rlon1 = ToRad(lon1);
            rlon2 = ToRad(lon2);

            dist = Math.Acos(Math.Sin(rlat1) * Math.Sin(rlat2) +
                Math.Cos(rlat1) * Math.Cos(rlat2) *
                Math.Cos(rlon2 - rlon1)) * R;

            /*
            double dLat = ToRad(lat2 - lat1);
            double dLon = ToRad(lon2 - lon1);

            double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
                Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(rlat1) * Math.Cos(rlat2);
            double c = 2* Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
            dist = R*c;
            */




            return dist;
        }
        /// <summary>
        /// GPS 데이터는 많지만 Cell ID데이터는 약 1km의 거리를 유지하기 떄문에 숫자가 맞지 않는다.
        /// 따라서 GPS 데이터의 시간에 맞는 데이터를 interpolation하여 숫자를 맞추어 돌려준다.
        /// </summary>
        /// <param name="st"></param>
        /// <param name="ed"></param>
        /// <param name="uid"></param>
        /// <returns></returns>
        public static Points GetGPSPointPair(DateTime sday, DateTime eday, string id)
        {
            Points point = new Points();
            string format = "yyyy-MM-dd HH:mm";
            string[] param = { id, sday.ToString(format), eday.ToString(format) };

            int first=0, cur=0, cnt=0;
            double pre_lat = 0, pre_lon = 0;

            // DB에 여기까지의 데이터를 얻어온다.
            // 첫 데이터를 얻어온다.
            DBMS dbm = DBMS.GetDBMS();
            dbm.Request("GPS_PAIR", param);

            dbm.Connect();
            while (dbm.Next())
            {
                double[] v = new double[4];

                if (dbm.data[0].ToString() != "")
                    v[0] = double.Parse(dbm.data[0].ToString());
                if (dbm.data[1].ToString() != "")
                    v[1] = double.Parse(dbm.data[1].ToString());
                if (dbm.data[2].ToString() != "")
                    v[2] = double.Parse(dbm.data[2].ToString());
                if (dbm.data[3].ToString() != "")
                    v[3] = double.Parse(dbm.data[3].ToString());
                // cell id 데이터가 동일하다면 일단 저장만 한다.

                Pot pot = new Pot();
                pot.gpsLat = v[0];
                pot.gpsLon = v[1];
                pot.Lat = v[2];
                pot.Lon = v[3];
                pot.Time = DateTime.Parse(dbm.data[4].ToString());

                point.mPt.Add(pot); cnt++;

                double aLat, bLat, aLon, bLon;

                // 새로운 cell id 가 나오면 interpolation 후 처음으로 돌아가서 데이터를 넣는다.
                if (pre_lat != v[2] && pre_lon != v[3])
                {
                    Pot pt = point.mPt[first];
                    if (first != cur)
                    {
                        aLat = (pot.Lat - pt.Lat) / (pot.Time - pt.Time).TotalSeconds;
                        bLat = pot.Lat - aLat * (pot.Time - sday).TotalSeconds;

                        aLon = (pot.Lon - pt.Lon) / (pot.Time - pt.Time).TotalSeconds;
                        bLon = pot.Lon - aLon * (pot.Time - sday).TotalSeconds;

                        for (int i = first + 1; i < cur + 1; i++)
                        {
                            point.mPt[i].Lat = aLat * (point.mPt[i].Time - sday).TotalSeconds + bLat;
                            point.mPt[i].Lon = aLon * (point.mPt[i].Time - sday).TotalSeconds + bLon;
                        }
                        first = cnt;
                    }
                    pre_lat = v[2]; pre_lon = v[3];
                    
                }

                cur = cnt; 
                

            }
            
            return point;
        }
        private static double ToRad(double angle)
        {
            return Math.PI * angle / 180.0;
        }
        public static int GetFakeGPStable(List<double[]> list,List<DateTime> list2)
        {
            int cnt = 0;

            DBMS dbm = DBMS.GetDBMS();            
            dbm.Request("COMPFAKE", null);

            dbm.Connect();
            while (dbm.Next())
            {
                double[] v = new double[4];

                if(dbm.data[0].ToString() != "")
                    v[0] = double.Parse(dbm.data[0].ToString());
                if (dbm.data[1].ToString() != "")
                    v[1] = double.Parse(dbm.data[1].ToString());
                if (dbm.data[2].ToString() != "")
                    v[2] = double.Parse(dbm.data[2].ToString());
                if (dbm.data[3].ToString() != "")
                    v[3] = double.Parse(dbm.data[3].ToString());
                DateTime dt = DateTime.Parse(dbm.data[4].ToString());
                list.Add(v);
                list2.Add(dt);
                cnt++;

            }

            return cnt;
        }
        public static double GetGap(DateTime dt, double lat, double lon)
        {
            int len = 0;
            DBMS dbm = DBMS.GetDBMS();
            string format = "yyyy-MM-dd HH:mm:ss";
            string[] param = { dt.ToString(format) };
            dbm.Request("COMPGPS", param);

            dbm.Connect();

            double[] lats = new double[8];
            double[] lons = new double[8];
            double res = -1;
            while (dbm.Next())
            {
                if (dbm.data[0].ToString() == "" || dbm.data[1].ToString() == "")
                    continue;
                lats[len] = double.Parse(dbm.data[0].ToString());
                lons[len] = double.Parse(dbm.data[1].ToString());
                len++;
            }
            for (int i = 0; i < len; i++)
            {
                double temp = GetDistance(lat, lon, lats[i], lons[i]);
                if (temp > 4)
                    continue;
                if (res < temp)
                    res = temp;
            }

            return res;
        }
        
    }
}


